#include <QSqlDatabase>
#include <QSqlError>
#include <QSqlQuery>
#include <QVariant>
#include <QString>
#include <QVector>
#include <QDebug>
#include <QStringList>

#include "FachadaBD.h"

FachadaBD::FachadaBD()
{
	crearConexion();

}

FachadaBD::~FachadaBD()
{


}


void FachadaBD::crearConexion()
{
	QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL");
	db.setDatabaseName("esteban");
	db.setUserName("esteban");
	db.setPassword("esteban");
	db.open();
}

QVector<QString> FachadaBD::validarUsuario(QString login, QString contrasena)
{
	QSqlQuery query;
	query.prepare("select login,contrasena,rol,idUsuario from Usuario where login = :login and contrasena = :contrasena AND estado = 'activo'");
	query.bindValue(":nombre", login);
	query.bindValue(":contrasena", contrasena);
	query.exec();
	query.first();
	QString loginTabla = query.value(0).toString();
	QString contrasenaTabla = query.value(1).toString();
	int rol  = query.value(2).toInt();
	int id  = query.value(3).toInt();
	QString rolTabla;
	rolTabla.setNum(rol);
	QString idUsuario;
	idUsuario.setNum(id);
	QVector<QString> datos;
	datos.resize(4);
	datos[0] = loginTabla;
	datos[1] = contrasenaTabla;
	datos[2] = rolTabla;
	datos[3] = idUsuario;
	qDebug() << datos;
	return datos;
}

QStringList FachadaBD::cargarRoles()
{
	QStringList roles;
	QSqlQuery query;
	query.prepare("select nombreRol from Rol");
	query.exec();
	while (query.next())
	{
		roles << query.value(0).toString();
	}
	return roles;
}

QStringList FachadaBD::cargarPersonasPrimerEstado()
{
	QStringList personas;
	
	QSqlQuery query;
	query.prepare("select login From Usuario,RolPorEstado where Usuario.rol = RolPorEstado.idRol AND RolPorEstado.idEstado IN(SELECT idEstado FROM Estado WHERE nombreEstado = 'nuevo')");
	query.exec();
	while (query.next())
	{
		personas << query.value(0).toString();
	}
	qDebug() << personas;
	return personas;
}

bool FachadaBD::crearUsuario(QString nombre, QString cedula, QString login, QString rol, QString estado)
{
	QSqlQuery idRol;
	idRol.prepare("SELECT idRol FROM Rol WHERE nombreRol = :rol");
	idRol.bindValue(":nombreRol", rol);
	idRol.exec();
	idRol.next();
	int idRolTabla = idRol.value(0).toInt();

	QSqlQuery query;
	query.prepare("INSERT INTO Usuario VALUES(0, :nombre, :cedula, :login, :contrasena, :rol, :estado, 0)");
	query.bindValue(":nombre", nombre);
	query.bindValue(":cedula", cedula);
	query.bindValue(":login", login);
	query.bindValue(":contrasena", login);
	query.bindValue(":rol", idRolTabla);
	query.bindValue(":estado", estado);

return query.exec();
}

QVector<QString> FachadaBD::consultarUsuario(QString id,QString cedula,QString login)
{
	QSqlQuery query;
	query.prepare("SELECT * FROM Usuario WHERE idUsuario = :id OR cedula = :cedula OR login = :login");
	query.bindValue(":id", id);
	query.bindValue(":cedula", cedula);
	query.bindValue(":login", login);
	query.exec();
	query.next();

	QVector<QString> consulta;
	consulta.resize(7);
	consulta[0] = query.value(0).toString();
	consulta[1] = query.value(1).toString();
	consulta[2] = query.value(2).toString();
	consulta[3] = query.value(3).toString();
	consulta[4] = query.value(4).toString();
	int idrol = query.value(5).toInt();
	consulta[6] = query.value(6).toString();
	

	QSqlQuery nombreRol;
	nombreRol.prepare("SELECT nombreRol FROM Rol WHERE idRol = :idrol");
	nombreRol.bindValue(":nombreRol", idrol);
	nombreRol.exec();
	nombreRol.next();
	QString nombreRolTabla = nombreRol.value(0).toString();

	consulta[5] = nombreRolTabla;

	qDebug() << consulta;
	return consulta;
}


bool FachadaBD::modificarUsuario(QString id, QString nombre, QString cedula, QString login, QString rol, QString estado)
{
	QSqlQuery idRol;
	idRol.prepare("SELECT idRol FROM Rol WHERE nombreRol = :rol");
	idRol.bindValue(":nombreRol", rol);
	idRol.exec();
	idRol.next();
	int idRolTabla = idRol.value(0).toInt();

	QSqlQuery query;
	query.prepare("UPDATE Usuario SET nombre = :nombre, cedula = :cedula, login = :login, contrasena = :contrasena, rol = :rol, estado = :estado WHERE idUsuario = :id");
	query.bindValue(":nombre", nombre);
	query.bindValue(":cedula", cedula);
	query.bindValue(":login", login);
	query.bindValue(":contrasena", login);
	query.bindValue(":rol", idRolTabla);
	query.bindValue(":estado", estado);
	query.bindValue(":id", id);

	qDebug() <<query.exec()<< query.lastError() << query.isValid();
	return query.exec();
}


bool FachadaBD::registrarIncidente(QString descripcion, QString prioridad, QString persona)
{
	QSqlQuery idPersona;
	idPersona.prepare("SELECT idUsuario FROM Usuario WHERE login = :persona");
	idPersona.bindValue(":personal", persona);
	idPersona.exec();
	idPersona.next();
	int idUsuario = idPersona.value(0).toInt();
	
	QSqlQuery id;
	id.exec("SELECT idEstado FROM Estado Where nombreEstado = 'nuevo'");
	id.next();
	int idEstado = id.value(0).toInt();
	
	QSqlQuery query;
	query.prepare("INSERT INTO Incidente VALUES(0, :descripcion, :prioridad, :idUsuario, :idEstado)");
	query.bindValue(":descripcion", descripcion);
	query.bindValue(":prioridad", prioridad);
	query.bindValue(":idUsuario", idUsuario);
	query.bindValue(":idEstado", idEstado);

	qDebug() << idUsuario;

	return query.exec();
}


bool FachadaBD::crearEstado(QString nombre)
{
	QSqlQuery query;
	query.prepare("INSERT INTO Estado VALUES(0, :nombre)");
	query.bindValue(":nombre", nombre);

return query.exec();
}

QVector<QString> FachadaBD::consultarEstado(QString id,QString nombre)
{
	QSqlQuery query;
	query.prepare("SELECT * FROM Estado WHERE idEstado = :id OR nombreEstado = :nombre");
	query.bindValue(":id", id);
	query.bindValue(":nombre", nombre);
	query.exec();
	query.next();

	QVector<QString> consulta;
	consulta.resize(2);
	consulta[0] = query.value(0).toString();
	consulta[1] = query.value(1).toString();

	qDebug() << consulta;
	return consulta;
}

bool FachadaBD::modificarEstado(QString id, QString nombre)
{
	QSqlQuery query;
	query.prepare("UPDATE Estado SET nombreEstado = :nombre WHERE idEstado = :id");
	query.bindValue(":nombre", nombre);
	query.bindValue(":id", id);

	qDebug() <<query.exec()<< query.lastError() << query.isValid();
	return query.exec();
}

bool FachadaBD::eliminarEstado(QString id, QString nombre)
{
	QSqlQuery query1;
	query1.exec("SELECT idEstado FROM Estado WHERE nombreEstado = 'huerfano'");
	query1.next();
	int idEstadoNuevo = query1.value(0).toInt();

	QSqlQuery query;
	query.prepare("UPDATE Incidente SET idEstadoActual = :idEstadoNuevo  WHERE idEstadoActual = :id");
	query.bindValue(":idEstadoNuevo", idEstadoNuevo);
	query.bindValue(":idEstadoActual", id);
	query.exec();

	QSqlQuery query2;
	query2.prepare("DELETE FROM Estado WHERE idEstado = :id AND nombreEstado = :nombre");
	query2.bindValue(":id", id);
	query2.bindValue(":nombre", nombre);

	return query2.exec();
}


QStringList FachadaBD::cargarEstados()
{
	QStringList estados;
	QSqlQuery query;
	query.prepare("select nombreEstado from Estado");
	query.exec();
	while (query.next())
	{
		estados << query.value(0).toString();
	}
	return estados;
}

bool FachadaBD::crearRelacion(QString estDominante, QString estDominado)
{
	QSqlQuery idEstDominante;
	idEstDominante.prepare("SELECT idEstado FROM Estado WHERE nombreEstado = :nombreEstado");
	idEstDominante.bindValue(":nombreEstado", estDominante);
	idEstDominante.exec();
	idEstDominante.next();
	int idEstDominant = idEstDominante.value(0).toInt();

	QSqlQuery idEstDominado;
	idEstDominado.prepare("SELECT idEstado FROM Estado WHERE nombreEstado = :nombreEstado");
	idEstDominado.bindValue(":nombreEstado", estDominado);
	idEstDominado.exec();
	idEstDominado.next();
	int idEstDominad = idEstDominado.value(0).toInt();

	QSqlQuery query;
	query.prepare("INSERT INTO RelacionEstado VALUES(:estDominante, :estDominado)");
	query.bindValue(":estDominante", idEstDominant);
	query.bindValue(":estDominado", idEstDominad);

return query.exec();
}

QString FachadaBD::consultarRelacion(QString estDominante, QString estDominado)
{
	QSqlQuery idEstDominante;
	idEstDominante.prepare("SELECT idEstado FROM Estado WHERE nombreEstado = :nombreEstado");
	idEstDominante.bindValue(":nombreEstado", estDominante);
	idEstDominante.exec();
	idEstDominante.next();
	int idEstDominant = idEstDominante.value(0).toInt();

	QSqlQuery idEstDominado;
	idEstDominado.prepare("SELECT idEstado FROM Estado WHERE nombreEstado = :nombreEstado");
	idEstDominado.bindValue(":nombreEstado", estDominado);
	idEstDominado.exec();
	idEstDominado.next();
	int idEstDominad = idEstDominado.value(0).toInt();

	QSqlQuery query;
	query.prepare("SELECT E1.nombreEstado, E2.nombreEstado FROM Estado E1, Estado E2, RelacionEstado R WHERE (E1.idEstado = R.idEstadoDominante AND E2.idEstado = R.idEstadoDominado) AND (R.idEstadoDominado = :estDominado OR R.idEstadoDominante = :estDominante)");
	query.bindValue(":estDominante", idEstDominant);
	query.bindValue(":estDominado", idEstDominad);
	query.exec();
	QString resultado;
	resultado = "ESTADO DOMINANTE/ESTADO DOMINADO\n";
	while (query.next()) {
		QString dominante = query.value(0).toString();
		QString dominado = query.value(1).toString();
		resultado += dominante+" / "+dominado+"\n";
	}
	return resultado;
}

bool FachadaBD::eliminarRelacion(QString estDominante, QString estDominado)
{
	QSqlQuery idEstDominante;
	idEstDominante.prepare("SELECT idEstado FROM Estado WHERE nombreEstado = :nombreEstado");
	idEstDominante.bindValue(":nombreEstado", estDominante);
	idEstDominante.exec();
	idEstDominante.next();
	int idEstDominant = idEstDominante.value(0).toInt();

	QSqlQuery idEstDominado;
	idEstDominado.prepare("SELECT idEstado FROM Estado WHERE nombreEstado = :nombreEstado");
	idEstDominado.bindValue(":nombreEstado", estDominado);
	idEstDominado.exec();
	idEstDominado.next();
	int idEstDominad = idEstDominado.value(0).toInt();

	QSqlQuery query;
	query.prepare("DELETE FROM RelacionEstado WHERE idEstadoDominante = :estDominante AND idEstadoDominado = :estDominado");
	query.bindValue(":estDominante", idEstDominant);
	query.bindValue(":estDominado", idEstDominad);

return query.exec();
}

bool FachadaBD::crearEstPorRol(QString rol, QString estado)
{
	QSqlQuery idRolTabla;
	idRolTabla.prepare("SELECT idRol FROM Rol WHERE nombreRol = :nombreRol");
	idRolTabla.bindValue(":nombreRol", rol);
	idRolTabla.exec();
	idRolTabla.next();
	int idRol = idRolTabla.value(0).toInt();

	QSqlQuery idEstadoTabla;
	idEstadoTabla.prepare("SELECT idEstado FROM Estado WHERE nombreEstado = :nombreEstado");
	idEstadoTabla.bindValue(":nombreEstado", estado);
	idEstadoTabla.exec();
	idEstadoTabla.next();
	int idEstado = idEstadoTabla.value(0).toInt();

	QSqlQuery query;
	query.prepare("INSERT INTO RolPorEstado VALUES(:idRol, :idEstado)");
	query.bindValue(":idRol", idRol);
	query.bindValue(":idEstado", idEstado);

	return query.exec();
}

QString FachadaBD::consultarEstPorRol(QString rol, QString estado)
{
	QSqlQuery idR;
	idR.prepare("SELECT idRol FROM Rol WHERE nombreRol = :nombreRol");
	idR.bindValue(":nombreRol", rol);
	idR.exec();
	idR.next();
	int idRol = idR.value(0).toInt();

	QSqlQuery idEst;
	idEst.prepare("SELECT idEstado FROM Estado WHERE nombreEstado = :nombreEstado");
	idEst.bindValue(":nombreEstado", estado);
	idEst.exec();
	idEst.next();
	int idEstado = idEst.value(0).toInt();

	QSqlQuery query;
	query.prepare("SELECT R.nombreRol, E.nombreEstado FROM Rol R, Estado E, RolPorEstado P WHERE (R.idRol = P.idRol AND E.idEstado = P.idEstado) AND (P.idRol = :idRol OR P.idEstado = :idEstado)");
	query.bindValue(":idRol", idRol);
	query.bindValue(":idEstado", idEstado);
	query.exec();
	QString resultado;
	resultado = "ROL/ESTADO\n";
	while (query.next()) {
		QString nombreRol = query.value(0).toString();
		QString nombreEstado = query.value(1).toString();
		resultado += nombreRol+" / "+nombreEstado+"\n";
	}
	return resultado;
}

bool FachadaBD::eliminarEstPorRol(QString rol, QString estado)
{
	QSqlQuery idR;
	idR.prepare("SELECT idRol FROM Rol WHERE nombreRol = :nombreRol");
	idR.bindValue(":nombreRol", rol);
	idR.exec();
	idR.next();
	int idRol = idR.value(0).toInt();

	QSqlQuery idEst;
	idEst.prepare("SELECT idEstado FROM Estado WHERE nombreEstado = :nombreEstado");
	idEst.bindValue(":nombreEstado", estado);
	idEst.exec();
	idEst.next();
	int idEstado = idEst.value(0).toInt();

	QSqlQuery query;
	query.prepare("DELETE FROM RolPorEstado WHERE idRol = :idRol AND idEstado = :idEstado");
	query.bindValue(":idRol", idRol);
	query.bindValue(":idEstado", idEstado);

return query.exec();
}



QVector<QVector <QString> > FachadaBD::cargarIncidentes(QString idUsuario)
{
	int comparaRol = QString::compare("1", idUsuario);
	if (comparaRol == 0)
	{
		qDebug() << "bugs para el admin";
		QSqlQuery incidente;

		incidente.prepare("SELECT I.idIncidente , I.descripcion,I.prioridad, E.nombreEstado FROM Incidente I, Estado E where (I.idEstadoActual IN(select idEstado from Estado where nombreEstado = 'huerfano') OR I.idUsuarioAsignado IN(select idUsuario from Usuario where estado = 'Inactivo')) AND I.idEstadoActual = E.idEstado");
		incidente.exec();

		QVector<QVector <QString> > datos;

		int a = 0;
		while (incidente.next()) {
			QString idIncidente = incidente.value(0).toString();
			QString descripcion = incidente.value(1).toString();
			QString prioridad = incidente.value(2).toString();
			QString nombreEstado = incidente.value(3).toString();

			datos.resize(datos.size() + 1);
			datos[a].resize(4);

			datos[a][0] = idIncidente;
			datos[a][1] = descripcion;
			datos[a][2] = prioridad;
			datos[a][3] = nombreEstado;

			a++;
		}

		qDebug() << datos;
		return datos;
	}
	else
	{

		QSqlQuery incidente;

		incidente.prepare("SELECT idIncidente , descripcion,prioridad, nombreEstado FROM Incidente, Estado WHERE idEstadoActual = idEstado AND idUsuarioAsignado = :idUsuario AND idEstadoActual NOT IN(SELECT idEstado FROM Estado WHERE nombreEstado = 'huerfano')");
		incidente.bindValue(":idUsuario", idUsuario);
		incidente.exec();

		QVector<QVector <QString> > datos;

		int a = 0;
		while (incidente.next()) {
			QString idIncidente = incidente.value(0).toString();
			QString descripcion = incidente.value(1).toString();
			QString prioridad = incidente.value(2).toString();
			QString nombreEstado = incidente.value(3).toString();

			datos.resize(datos.size() + 1);
			datos[a].resize(4);

			datos[a][0] = idIncidente;
			datos[a][1] = descripcion;
			datos[a][2] = prioridad;
			datos[a][3] = nombreEstado;

			a++;
		}

		qDebug() << datos;
		return datos;
	}
}

bool FachadaBD::cargarDocumentacion( QString idIncidente, QString documento)
{
	QSqlQuery query;
	query.prepare("INSERT INTO Documentacion VALUES(0, :idIncidente, :documento)");
	query.bindValue(":idIncidente", idIncidente);
	query.bindValue(":documento", documento);

return query.exec();
}

QStringList FachadaBD::nuevosEstados(QString estadoActual)
{
	QStringList estados;

	QSqlQuery query1;
	query1.prepare("select idEstado from Estado WHERE nombreEstado = :estado");
	query1.bindValue(":estado", estadoActual);
	query1.exec();
	query1.next();
	int idEstadoActual = query1.value(0).toInt();

	QSqlQuery query;
	query.prepare("SELECT nombreEstado FROM Estado WHERE idEstado IN(SELECT idEstadoDominado FROM RelacionEstado WHERE idEstadoDominante = :idEstado)");
	query.bindValue(":idEstado", idEstadoActual);
	query.exec();
	while (query.next())
	{
		estados << query.value(0).toString();
	}
	return estados;
}

QStringList FachadaBD::nuevosUsuarios(QString estadoActual)
{
	QStringList usuarios;

	QSqlQuery query1;
	query1.prepare("select idEstado from Estado WHERE nombreEstado = :estado");
	query1.bindValue(":estado", estadoActual);
	query1.exec();
	query1.next();
	int idEstadoActual = query1.value(0).toInt();

// select Usuario.nombre from Usuario where Usuario.rol IN (select RolPorEstado.idRol from RolPorEstado where RolPorEstado.idEstado IN (select idEstadoDominado from RelacionEstado where idEstadoDominante = 1));

	QSqlQuery query;
	query.prepare("select Usuario.nombre from Usuario where Usuario.rol IN (select RolPorEstado.idRol from RolPorEstado where RolPorEstado.idEstado = :idEstado)");
	query.bindValue(":idEstado", idEstadoActual);
	query.exec();
	while (query.next())
	{
		usuarios << query.value(0).toString();
	}
	return usuarios;
}

bool FachadaBD::asignarIncidente(QString incidente, QString estado, QString usuario)
{
	QSqlQuery query1;
	query1.prepare("SELECT idEstado FROM Estado WHERE nombreEstado = :estado");
	query1.bindValue(":estado", estado);
	query1.exec();
	query1.next();
	int idEstado = query1.value(0).toInt();

	QSqlQuery query2;
	query2.prepare("SELECT idUsuario FROM Usuario WHERE nombre = :usuario");
	query2.bindValue(":usuario", usuario);
	query2.exec();
	query2.next();
	int idUsuario = query2.value(0).toInt();

	QSqlQuery query;
	query.prepare("UPDATE Incidente SET idEstadoActual = :idEstado, idUsuarioAsignado = :idUsuario WHERE idIncidente = :incidente");
	query.bindValue(":idEstado", idEstado);
	query.bindValue(":idUsuario", idUsuario);
	query.bindValue(":idIncidente", incidente);

	return query.exec();

}

QString FachadaBD::usuario(QString incidente)
{
	QSqlQuery query2;
	query2.prepare("SELECT idUsuarioAsignado, idEstadoActual, Usuario.estado  FROM Incidente, Usuario WHERE idIncidente = :incidente AND idUsuarioAsignado = Usuario.idUsuario;");
	query2.bindValue(":incidente", incidente);
	query2.exec();
	query2.next();
	QString idUsuario = query2.value(0).toString();
	QString idEstadoActual = query2.value(1).toString();
	QString estadoUsuario = query2.value(2).toString();

	int comparaEstado = QString::compare("Inactivo", estadoUsuario);
	int estado = QString::compare("1", idEstadoActual);
	if((comparaEstado == 0) || (estado == 0))
	{
		QString resultado = "1";
		return resultado;
	}
	else
	{
	return idUsuario;
	}
}

void FachadaBD::registrarHistorial(QString usuario, QString comentario, QString idIncidente)
{
	QSqlQuery query2;
	query2.prepare("INSERT INTO Historial VALUES(0,:usuario,:comentario,:idIncidente,NOW())");
	query2.bindValue(":usuario", usuario);
	query2.bindValue(":comentario", comentario);
	query2.bindValue(":idIncidente", idIncidente);
	query2.exec();
	qDebug() <<"historial "<< query2.exec() << query2.lastError();
}

QStringList FachadaBD::verUsuarios()
{
	QStringList usuarios;
	QSqlQuery query;
	query.exec("SELECT login From Usuario");
	while (query.next())
	{
		usuarios << query.value(0).toString();
	}
	return usuarios;
}

QVector<QVector <QString> > FachadaBD::cargarHistorial(QString usuario)
{
	int idUsuario;
	QSqlQuery query1;
	query1.prepare("SELECT idUsuario From Usuario where login = :usuario");
	query1.bindValue(":usuario", usuario);
	query1.exec();
	query1.next();
	idUsuario = query1.value(0).toInt();

	qDebug() << "idUsuario en historial"<< idUsuario;

	QSqlQuery incidente;
	incidente.prepare("SELECT Historial.idIncidente, Usuario.login, Historial.modificacion, Historial.fechaHora FROM Historial, Usuario WHERE Historial.idUsuario = Usuario.idUsuario AND idIncidente IN (SELECT idIncidente FROM Historial WHERE idUsuario = :idUsuario)");
	incidente.bindValue(":idUsuario", idUsuario);
	incidente.exec();

	QVector<QVector <QString> > datos;

	int a = 0;
	while (incidente.next()) {
		QString idIncidente = incidente.value(0).toString();
		QString nombre = incidente.value(1).toString();
		QString modificacion = incidente.value(2).toString();
		QString fechaHora = incidente.value(3).toString();

		datos.resize(datos.size() + 1);
		datos[a].resize(4);

		datos[a][0] = idIncidente;
		datos[a][1] = nombre;
		datos[a][2] = modificacion;
		datos[a][3] = fechaHora;

		a++;
	}

	qDebug() <<"historial incidente" <<datos;
	return datos;
}

bool FachadaBD::cambiarContrasena(QString login, QString contrasenaA, QString contrasenaN)
{
	QSqlQuery query;
	query.prepare("UPDATE Usuario SET contrasena = :contrasenaN WHERE login = :login AND contrasena = :contrasenaA");
	query.bindValue(":contrasenaN", contrasenaN);
	query.bindValue(":login", login);
	query.bindValue(":contrasenaA", contrasenaA);
	return query.exec();
}